package com.jnc.pay;

import com.jnc.pay.core.model.HttpClientPro;
import com.jnc.pay.core.model.HttpServerPro;
import com.jnc.pay.core.model.VertxPro;
import com.jnc.pay.core.vertx.ObjectCodec;
import io.vertx.core.Vertx;
import io.vertx.core.VertxOptions;
import io.vertx.core.eventbus.DeliveryOptions;
import io.vertx.core.http.HttpClientOptions;
import io.vertx.core.http.HttpServerOptions;
import io.vertx.ext.web.client.WebClientOptions;
import lombok.extern.slf4j.Slf4j;
import org.mybatis.spring.annotation.MapperScan;
import org.redisson.Redisson;
import org.redisson.api.RedissonClient;
import org.redisson.config.Config;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.*;
import org.springframework.core.io.ClassPathResource;

import java.io.IOException;

@Slf4j
@SpringBootApplication
@MapperScan("com.jnc.pay.**.mapper")
public class Server {
    @Value("${event.timeout}")
    private int eventTimeout; //事件超时时间
    @Value("${server.port}")
    private int port;
    @Autowired
    private VertxPro vertxPro;
    @Autowired
    private HttpClientPro httpClientPro;
    @Autowired
    private HttpServerPro httpServerPro;


    public static void main(String[] args) {
        SpringApplication.run(Server.class);
        log.info("server start......");
    }

    /**
     * 初始化Vertx实例
     * @return
     */
    @Bean
    public Vertx getVertx() {
        VertxOptions options = new VertxOptions();
        options.setBlockedThreadCheckInterval(vertxPro.getBlockedThreadCheckInterval());   //阻塞线程检查的时间间隔，默认1000，单位ms，即1秒；
        options.setMaxEventLoopExecuteTime(vertxPro.getMaxEventLoopExecuteTime());   //Event Loop的最大执行时间，默认2L * 1000 * 1000000，单位ns，即2秒；
        options.setMaxWorkerExecuteTime(vertxPro.getMaxWorkerExecuteTime());  //Worker线程的最大执行时间，默认60l * 1000 * 1000000，单位ns，即60秒；
        options.setWorkerPoolSize(vertxPro.getWorkerPoolSize());  //设置Vert.x实例中支持的Worker线程的最大数量，默认值为20；
        options.setEventLoopPoolSize(vertxPro.getEventLoopPoolSize()); //设置Vert.x实例中使用的Event Loop线程的数量，默认值为：2的n次方
        //如果线程阻塞时间超过了这个阀值，那么就会打印警告的堆栈信息，默认为5l * 1000 * 1000000，单位ns，即5秒；
        options.setWarningExceptionTime(vertxPro.getWarningExceptionTime());
        Vertx vertx = Vertx.vertx(options);
        //注册一个编解码器到eventbus：主要用于实体传输时的编解码。
        vertx.eventBus().registerCodec(new ObjectCodec());
        return vertx;
    }

    /**
     * 初始化Http客户端参数
     * @return
     */
    @Bean
    public HttpClientOptions getHttpClientOptions() {
        HttpClientOptions options = new HttpClientOptions();
        options.setConnectTimeout(httpClientPro.getConnectTimeout()); //http连接超时时间,单位毫秒ms
        options.setIdleTimeout(httpClientPro.getIdleTimeout());//http连接空闲超时时间,单位秒s
        options.setKeepAlive(httpClientPro.isKeepAlive());//是否保持长连接
        options.setMaxPoolSize(httpClientPro.getMaxPoolSize());//最大线程数
        options.setTcpNoDelay(httpClientPro.isTcpNoDelay());//设置是否禁用Nagle算法，设置true后禁用Nagle算法，默认为false（即默认启用Nagle算法）
        options.setMaxWaitQueueSize(httpClientPro.getMaxWaitQueueSize());//最大请求等待队列长度，负数则代表无限制
        options.setUsePooledBuffers(httpClientPro.isUsePooledBuffers());//设置是否启用Netty池缓冲区,true启用
        options.setPipelining(httpClientPro.isPipelining());//设置是否启用管道，true启用
        return options;
    }

    /**
     * 初始化Http服务端参数
     * @return
     */
    @Bean
    public HttpServerOptions getHttpServerOptions() {
        HttpServerOptions options = new HttpServerOptions();
        options.setHost(httpServerPro.getHost());   //设置服务ip
        options.setPort(port);   //设置服务端口
        options.setReceiveBufferSize(httpServerPro.getReceiveBufferSize());  //设置接收buffer的size
        options.setTcpKeepAlive(httpServerPro.isTcpKeepAlive());  //设置TCP是否保持激活  true:激活
        options.setTcpNoDelay(httpServerPro.isTcpNoDelay());  //设置是否启用TCP不延迟  true:不延迟
        options.setHandle100ContinueAutomatically(httpServerPro.isHandle100ContinueAutomatically()); //设置是否继续自动处理100
        options.setMaxChunkSize(httpServerPro.getMaxChunkSize());  //设置最大的HTTP块大小
        return options;
    }

    /**
     * 初始化WebClient参数
     * @return
     */
    @Bean
    public WebClientOptions getWebClientOptions(){
        WebClientOptions options = new WebClientOptions();
        options.setConnectTimeout(httpClientPro.getConnectTimeout()); //http连接超时时间,单位毫秒ms
        options.setIdleTimeout(httpClientPro.getIdleTimeout());//http连接空闲超时时间,单位秒s
        options.setKeepAlive(httpClientPro.isKeepAlive());//是否保持长连接
        options.setMaxPoolSize(httpClientPro.getMaxPoolSize());//最大线程数
        options.setTcpNoDelay(httpClientPro.isTcpNoDelay());//设置是否禁用Nagle算法，设置true后禁用Nagle算法，默认为false（即默认启用Nagle算法）
        options.setMaxWaitQueueSize(httpClientPro.getMaxWaitQueueSize());//最大请求等待队列长度，负数则代表无限制
        options.setUsePooledBuffers(httpClientPro.isUsePooledBuffers());//设置是否启用Netty池缓冲区,true启用
        options.setPipelining(httpClientPro.isPipelining());//设置是否启用管道，true启用
        return options;
    }

    /**
     * 初始化发送或发布消息及消息头参数
     * @return
     */
    @Bean
    public DeliveryOptions getDeliveryOptions() {
        DeliveryOptions options = new DeliveryOptions();
        options.setCodecName("ObjectCodec");  //设置编码名称(跟编解码器的名称一致)
        options.setSendTimeout(eventTimeout);  //设置发送响应消息的超时时间；如果超时，则调用处理程序失败
        return options;
    }

    /**
     * 初始化redisson
     * @return
     * @throws IOException
     */
    @Bean
    public RedissonClient redissonClient() throws IOException {
        return Redisson.create(Config.fromYAML(new ClassPathResource("redisson.yml").getInputStream()));
    }
}
